/**
 * fulihui.com Inc.
 * Copyright (c) 2015-2016 All Rights Reserved.
 */
package com.fulihui.usercore.core.processor.auth;

import com.fulihui.usercore.biz.shard.UserManager;
import com.fulihui.usercore.biz.shard.WechatUserManager;
import com.fulihui.usercore.common.util.Errors;
import com.fulihui.usercore.common.util.PasswordUtil;
import com.fulihui.usercore.core.repository.LoginHelpRepository;
import com.fulihui.usercore.core.repository.UserLoginRepository;
import com.fulihui.usercore.core.repository.WechatUnionidHelpRepository;
import com.fulihui.usercore.core.repository.WechatUserRepository;
import com.fulihui.usercore.dal.dataobj.LoginDO;
import com.fulihui.usercore.dal.dataobj.LoginHelpDO;
import com.fulihui.usercore.dal.dataobj.WechatUnionidHelpDOExample;
import com.fulihui.usercore.dto.UserDTO;
import com.fulihui.usercore.dto.WechatUserDTO;
import com.fulihui.usercore.enums.*;
import com.fulihui.usercore.request.auth.AbstractAuthRequest;
import com.fulihui.usercore.request.auth.AccountAndBindingWechatAuthRequest;
import com.fulihui.usercore.request.user.UserSetPasswdRequest;
import org.apache.commons.lang3.RandomStringUtils;
import org.jboss.resteasy.util.Base64;
import org.near.servicesupport.error.InvokeServiceException;
import org.near.toolkit.common.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.Collections.singletonList;

/**
 * @author zhangyingjie
 * @version $Id: v 0.1 2017年07月18日 17:29 zhangyingjie Exp $
 */
@Component("accountBindingWechatAuthProcessor")
public class AccountBindingWechatAuthProcessor extends AbstractAuthProcessor{
    private final Logger log = LoggerFactory.getLogger(AccountBindingWechatAuthProcessor.class);
    @Autowired
    private WechatUserManager wechatUserManager;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private WechatUserRepository wechatUserRepository;
    @Autowired
    private WechatUnionidHelpRepository wechatUnionidHelpRepository;
    @Autowired

    private UserManager userManager;
    @Autowired
    private UserLoginRepository userLoginRepository;
    @Autowired
    private LoginHelpRepository loginHelpRepository;

    @Override
    public String authType() {
        return UserRegisterTypeEnum.ACCOUNT_BINDING_WECHAT.getCode();
    }
    /**
     * 重写注册方法，验证 验证码，然后调用父register通用方法
     * @param request
     * @return
     */
    @Override
    public String register(AbstractAuthRequest request) {
        String userId = "";
        AccountAndBindingWechatAuthRequest bindingWechatAuthRequest = (AccountAndBindingWechatAuthRequest) request;
        log.info("耳朵资讯注册request：{}",bindingWechatAuthRequest);
        if (!checkSmsCode(bindingWechatAuthRequest.getLoginId(), bindingWechatAuthRequest.getVcode(),
                bindingWechatAuthRequest.getVcodeNamespace())) {
            throw new InvokeServiceException(Errors.VCode.VCODE_VALIDATION_FAILS);
        }
        WechatUnionidHelpDOExample example = new WechatUnionidHelpDOExample();
        example.createCriteria().andUnionidEqualTo(bindingWechatAuthRequest.getUnionid());
//        WechatUserExample example = new WechatUserExample();
//        WechatUserExample.Criteria criteria = example.createCriteria();
//        criteria.andUnionidEqualTo(bindingWechatAuthRequest.getUnionid());
        //fixme 调用辅助表
        List<WechatUserDTO> wechatUserDTOList = wechatUnionidHelpRepository.query(example);
        if(CollectionUtils.isEmpty(wechatUserDTOList)){
            log.info("还未关注哇哈哈福礼惠公众号request：{}",bindingWechatAuthRequest);
            userId = transactionTemplate.execute(status -> {
                String _userid= super.register(request);
                //绑定微信
                WechatUserDTO wechatUserDTO = this.buildWechatUserDTO(_userid, bindingWechatAuthRequest);
                wechatUserManager.bindingByUserId(wechatUserDTO);
                return _userid;
            });
        }else{
            log.info("已关注哇哈哈福礼惠公号，无需再注册，直接绑定native 授权信息即可");
            //有微信绑定信息，证明公众号已经登录过，不需要产生新的userid，直接绑定native 授权信息即可
            if (wechatUserDTOList.size()==1 && StringUtil.equals(WechatOpenIdTypeEnum.WECHAT_MP.getCode(),
                    wechatUserDTOList.get(0).getOpenidType())){
                WechatUserDTO wechatUserDTO = wechatUserDTOList.get(0);
                wechatUserDTO = this.buildWechatUserDTO(wechatUserDTO.getUserId(), bindingWechatAuthRequest);
                //绑定微信
                wechatUserManager.bindingByUserId(wechatUserDTO);
                userId = wechatUserDTO.getUserId();
                log.info("已关注哇哈哈福礼惠公号，绑定native成功，userid：{}",userId);
                //修改手机号
                boolean completeB = completeMobile(bindingWechatAuthRequest.getLoginId(), userId);
                if (completeB){
                    log.info("修改用户手机号成功！loginId:{}",bindingWechatAuthRequest.getLoginId());
                }else{
                    log.info("修改用户手机号有误！loginId:{}",bindingWechatAuthRequest.getLoginId());
                }
                //设置密码
                UserSetPasswdRequest userSetPasswdRequest =
                        buildSetPasswdRequest(bindingWechatAuthRequest.getLoginId(), bindingWechatAuthRequest.getPassword());
                userManager.setPasswd(userSetPasswdRequest);
                //设置user信息
                UserDTO userDTO = toUserModel(bindingWechatAuthRequest);
                userDTO.setUserId(userId);
                userRepository.modify(userDTO);
            }else{
                throw new InvokeServiceException(Errors.User.WECHAT_HAS_BINDING_USER);
            }
        }
        return userId;
    }

    /**
     * 组装 修改密码request
     * @param loginId
     * @param passwd
     * @return
     */
    private UserSetPasswdRequest buildSetPasswdRequest(String loginId,String passwd){
        UserSetPasswdRequest request = new UserSetPasswdRequest();
        request.setLoginId(loginId);
        request.setPasswd(passwd);
        return request;
    }

    /**
     * 修改手机号
     * @param mobileno
     * @param userId
     * @return
     */
    private boolean completeMobile(final String mobileno,final String userId){
        // 使用事务模版将事务往上提
        boolean flag = transactionTemplate.execute(status->{
            //fixme 如果补充手机号，调用此方法，证明usr_login表的login_id存的是unionid,需把辅助表的数据删掉，再重新插入一条
            //fixme 这里不对旧数据loginid是否为手机号进行验证，因为微信登录用的授权登录，此处loginid存的值为unionid
            LoginDO oldLoginDO = userLoginRepository.queryByUserId(userId);
            if (oldLoginDO == null){
                status.setRollbackOnly();
                return false;
            }
            //删除 旧的数据  login_id(unionid)
            boolean delete = loginHelpRepository.delete(oldLoginDO.getLoginId());
            if (!delete){
                status.setRollbackOnly();
                return false;
            }
            //重新插入一条
            LoginHelpDO record = new LoginHelpDO();
            record.setUserId(userId);
            record.setLoginId(mobileno);
            boolean insert = loginHelpRepository.insert(record);
            if (!insert){
                status.setRollbackOnly();
                return false;
            }

            //修改登录表
            LoginDO loginDO = new LoginDO();
            loginDO.setUserId(userId);
            loginDO.setLoginId(mobileno);
            boolean update1 = userLoginRepository.updateLoginId(loginDO);

            //修改用户详情表
            UserDTO userDTO = new UserDTO();
            userDTO.setUserId(userId);
            userDTO.setMobileNo(userId);
            userDTO.setMemo(userId);
            boolean update2 = userRepository.modify(userDTO);
            if(update1 && update2){
                return true;
            }
            status.setRollbackOnly();
            return false;
        });
        return flag;
    }
    /**
     * 组装绑定微信dto
     * @param userId
     * @param request
     * @return
     */
    private WechatUserDTO buildWechatUserDTO(String userId,AccountAndBindingWechatAuthRequest request){
        WechatUserDTO record = new WechatUserDTO();
        record.setOpenId(request.getOpenid());
        record.setOpenidType(request.getOpenidType());
        record.setUnionid(request.getUnionid());
        record.setUserId(userId);
        return record;
    }
    /**
     * 重写父类方法，加入密码注册
     * @param request {@link AbstractAuthRequest} 的子类
     * @return {@link LoginDO}
     */
    @Override
    protected LoginDO toLoginModel(String userId, AbstractAuthRequest request) {
        AccountAndBindingWechatAuthRequest bindingWechatAuthRequest = (AccountAndBindingWechatAuthRequest) request;
        LoginDO loginDO = new LoginDO();
        loginDO.setLoginId(bindingWechatAuthRequest.getLoginId());
        loginDO.setUserId(userId);
        loginDO.setSalt(RandomStringUtils.randomAlphanumeric(16));
        loginDO.setPassword(PasswordUtil.encryptPassword(loginDO.getLoginId(),bindingWechatAuthRequest.getPassword(),loginDO.getSalt()));
        return loginDO;
    }
    @Override
    UserDTO toUserModel(AbstractAuthRequest request) {
        AccountAndBindingWechatAuthRequest bindingWechatAuthRequest = (AccountAndBindingWechatAuthRequest) request;
        UserDTO userDTO = new UserDTO();
        userDTO.setRegisterType(authType());
        userDTO.setRegisterSource(request.getRegisterSource());
        userDTO.setGender(UserGenderEnum.UNKNOW.getCode());
        if (StringUtil.isNotBlank(bindingWechatAuthRequest.getNickname())){
            userDTO.setNickname(bindingWechatAuthRequest.getNickname());
        }else{
            userDTO.setNickname(nicknameGenerator.generate());
        }
        if (StringUtil.equals("男",bindingWechatAuthRequest.getSex())) {
            userDTO.setGender(UserGenderEnum.MEN.getCode());
        } else if (StringUtil.equals("女",bindingWechatAuthRequest.getSex())) {
            userDTO.setGender(UserGenderEnum.WOMEN.getCode());
        } else {
            userDTO.setGender(UserGenderEnum.UNKNOW.getCode());
        }
        //头像
        if (StringUtil.isNotBlank(bindingWechatAuthRequest.getHeadImg())){
            userDTO.setHeadImg(bindingWechatAuthRequest.getHeadImg());
        }

        // 快捷登陆账号就是手机号
        userDTO.setMobileNo(request.getLoginId());
        userDTO.setMobileVerified(BooleanValueEnum.TRUE.isTrue());

        userDTO.setState(UserStateEnum.NOMAL.getCode());
        userDTO.setRoleCode("USER_NOMAL");
        userDTO.setProvince(request.getProvince());
        userDTO.setCity(request.getCity());
        Date now = new Date();
        userDTO.gmtCreate(now);
        userDTO.lastLogin(now);
        userDTO.setErduoVersion(request.getErduoVersion());

        if (request.getUsedProduct() != null) {
            userDTO.setUsedProducts(singletonList(request.getUsedProduct()));
        }
        Map<String, Object> param = new HashMap<>();
        if (StringUtil.isNotBlank(request.getUserIP())) {
            param.put("userIp", request.getUserIP());
        }
        try {
            Map<String, String> extMap = new HashMap<>();
            if (StringUtil.isNotBlank(userDTO.getNickname())){
                extMap.put("screen_name", Base64.encodeBytes(userDTO.getNickname().getBytes(), Base64.URL_SAFE).toString());
            }else{
                extMap.put("screen_name", "");
            }
            extMap.put("profile_image_url", userDTO.getHeadImg()==null?"":userDTO.getHeadImg());
            extMap.put("gender", bindingWechatAuthRequest.getSex()==null?"":bindingWechatAuthRequest.getSex());
            extMap.put("province",userDTO.getProvince()==null?"":userDTO.getProvince());
            extMap.put("city", userDTO.getCity()==null?"":userDTO.getCity());
            extMap.put("country", bindingWechatAuthRequest.getCountry()==null?"":bindingWechatAuthRequest.getCountry());
            param.put("WechatInfo",extMap);
        }catch (Exception e){

        }
        if (param.size() > 0) {
            userDTO.setExtInfo(param);
        }

        return userDTO;
    }

    /**
     * 登录用 账号和密码登录,此处理器只用来注册，不实现登录方法
     * @param request {@link AbstractAuthRequest}
     * @return
     */
    @Override
    public String login(AbstractAuthRequest request) {
        return null;
    }
}
